package com.ieds.web.utils;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;

import javax.activation.MimetypesFileTypeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;

/**
 * @Auther: wanglei
 * @Date: 2020.07.06
 * @Description: com.ieds.web.utils
 */
public class FileUtil {
    //判断文件类型：目前有两种方式：一种为读取文件头来判断，另一种则直接根据扩展名，暂时使用后者，使用MimetypesFileTypeMap第三方工具，
    //可以通过扩展resource/META-INF/mime.types来定义新的文件类型
    private static MimetypesFileTypeMap m = new MimetypesFileTypeMap();

    /**
     * 根据ResFile的contentType判断并返回文件类型的中文名称，例如视频、音频等。
     * 可返回的文件类型有：
     * 视频
     * 音频
     * 图像
     * 文本
     * 文档
     * 压缩包
     * 其它
     *
     * @param contentType
     * @return
     */
    public static String getDispalyFileType(String contentType) {
        if (StringUtils.isEmpty(contentType)) {
            return "未知";
        }

        if (contentType.startsWith("image")) {
            return "图像";
        } else if (contentType.startsWith("video")) {
            return "视频";
        } else if (contentType.startsWith("audio")) {
            return "音频";
        } else if (contentType.contains("application/zip") ||
                contentType.contains("x-rar-compressed") ||
                contentType.contains("x-7z-compressed") ||
                contentType.contains("x-gzip") ||
                contentType.contains("x-tar")) {
            return "压缩包";
        } else if (contentType.contains("msword") ||
                contentType.contains("ms-excel") ||
                contentType.contains("ms-powerpoint") ||
                contentType.contains("ms-excel")) {
            return "OFFICE文档";
        } else if (contentType.contains("text/plain")) {
            return "文本";
        }

        return "其它";
    }

    /**
     * 判断文件类型
     *
     * @param filePath
     * @return
     * @throws IOException
     */
    public static String detectFileContentType(String filePath) throws IOException {
        return detectFileContentTypeByExt(filePath);
    }

    /**
     * 根据传入的id（通常是用户id、组织id、库id和文件id），生成对应的两级目录，
     * 从而避免太多目录带来的性能下降的问题。
     *
     * （原理：取得uuid的hashcode与0xff按位与操作生成0-255的整数作为一级目录；
     * 右移8位，也即除以256，与0xff按位与生成0-255的整数作为二级目录）
     *
     * @param uuid
     * @return
     */
    public static String generateFolderPath(String uuid) {
        int dir1 = uuid.hashCode()&0xff;
        int dir2 = (uuid.hashCode()>>8)&0xff;

        return dir1 + File.separator + dir2;
    }

    /**
     * 计算文件夹/文件的大小
     *
     * @param file
     * @return
     */
    public static long getFileSize(File file) {
        //判断文件是否存在
        if (file.exists()) {
            //如果是目录则递归计算其内容的总大小，如果是文件则直接返回其大小
            if (!file.isFile()) {
                //获取文件大小
                File[] fl = file.listFiles();
                long size = 0L;
                for (File f : fl)
                    size += getFileSize(f);
                return size;
            } else {
                return file.length();
            }
        } else {
            System.out.println("文件或者文件夹不存在，请检查路径是否正确！");
            return 0;
        }
    }

    public static int getFileCount(File file) {
        //判断文件是否存在
        if (file.exists()) {
            //如果是目录则递归统计
            if (!file.isFile()) {
                //获取文件大小
                File[] fl = file.listFiles();
                int count = 0;
                for (File f : fl)
                    count += getFileCount(f);
                return count;
            } else {
                return 1;
            }
        } else {
            System.out.println("文件或者文件夹不存在，请检查路径是否正确！");
            return 0;
        }
    }

    /**
     * 将long型的空间信息格式化为KB/MB/GB/TB的形式
     *
     * @param size
     * @return
     */
    public static String getFormatSize(long size) {

        long kb = (size+1024)/1024;
        long mb = kb/1024;
        long gb = mb/1024;
        long tb = gb/1024;

        if (tb>1024) {
            //只显示pb
            return String.format("%.2fPB", tb/1024.0);
        } else if (gb>1024) {
            //只显示tb
            return String.format("%.2fTB", gb/1024.0);
        } else if (mb>1024) {
            //只显示gb
            return String.format("%.2fGB", mb/1024.0);
        } else if (kb>1024) {
            //只显示mb
            return String.format("%.2fMB", kb/1024.0);
        } else {
            return String.format("%.2fKB", kb/1.0);
        }

    }

    /**
     * 自动判断文件类型（根据扩展名）
     *
     * @param filePath
     * @return
     * @throws IOException
     */
    private static String detectFileContentTypeByExt(String filePath) throws IOException {
        return m.getContentType(filePath.toLowerCase());
    }

    public static void main(String[] args) {
        long size = 144;
        System.out.println(FileUtil.getFormatSize(size));
    }

    /**
     * @param: [response, request, filePath, saveFileName]
     * @return: void
     * @date: 2020.07.06 13:14
     * @Title：downloadAttachment
     * @Description 文件下载
     */
    public static void downloadAttachment(HttpServletResponse response, HttpServletRequest request , String filePath, String saveFileName) {

        response.reset();
        //response.setContentType("application/octet-stream;charset=utf-8");
        response.setContentType(getContentType(saveFileName));
        // response.setContentType("application/x-download");
        OutputStream outp = null;
        FileInputStream in = null;
        try {
            response.addHeader("Content-Disposition", "attachment;filename=\""+ encodeFilename(request,saveFileName)+"\"");//名称两边的双引号不能省略 兼容火狐 文件名中的空格
            outp = response.getOutputStream();
            in = new FileInputStream(filePath);
            byte[] b = new byte[1024];
            int i = 0;
            while ((i = in.read(b)) > 0) {
                outp.write(b, 0, i);
            }
            outp.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                in = null;
            }
            if (outp != null) {
                try {
                    outp.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                outp = null;
            }
        }
    }

    /**
     * @param: [request, fileName]
     * @return: java.lang.String
     * @date: 2020.07.06 13:15
     * @Title：encodeFilename
     * @Description文件名解码
     */
    private static String encodeFilename(HttpServletRequest request,String fileName) throws UnsupportedEncodingException{

        String agent =request.getHeader("USER-AGENT");

        try {
            // IE
            if (null != agent && -1 != agent.indexOf("MSIE")) {
                fileName = URLEncoder.encode(fileName, "UTF-8");
                // Firefox
            } else if (null != agent && -1 != agent.indexOf("Mozilla")) {
                fileName = new String( fileName.getBytes("UTF-8"), "ISO-8859-1" );
            }
        } catch (UnsupportedEncodingException e) {
            try {
                fileName = new String(fileName.getBytes("UTF-8"),"iso-8859-1");
            } catch (UnsupportedEncodingException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }
        return fileName;
    }


    /**
     * @param: [fileName]
     * @return: java.lang.String
     * @date: 2020.07.06 13:15
     * @Title：getContentType
     * @Description 获取文件类型
     */
    private static String getContentType(String fileName){

        String ext = FilenameUtils.getExtension(fileName).toLowerCase();
        if (ext.equals(".zip")) {
            return "application/zip";
        } else if (ext.equals(".xls") || ext.equals(".xlsx")) {
            return "application/x-excel";
        } else if (ext.equals(".doc") || ext.equals(".docx")) {
            return "application/msword";
        } else if (ext.equals(".pdf")) {
            return "application/pdf";
        } else if (ext.equals(".jpg") || ext.equals(".jpeg")) {
            return "image/jpeg";
        } else if (ext.equals(".gif")) {
            return "image/gif";
        } else if (ext.equals(".png")) {
            return "image/png";
        }else if(ext.equals(".bmp")){
            return "image/bmp";
        }
        return "application/force-download";
    }
}
